/**
 * @author     Gabor Greif <ggreif@gmail.com>
 * @copyright  2009-2010 Gabor Greif
 * @license    http://www.opensource.org/licenses/mit-license.php  MIT License
 * @version    Release: 0.0
 */

#ifndef micker_ENV_hpp
#define micker_ENV_hpp

#include <string>

namespace micker {

    /// @brief Env - common base class for command environments
    class Env
    {
    public:
        virtual ~Env(void)
            {}
    };

    /// @brief ValEnv - environment consisting of just one value
    /// @note defaults to default constructed value
    template <typename T>
    struct ValEnv : Env, T
    {
        typedef ValEnv simplify;
        typedef const T& from;
        typedef T& preferred;
        preferred pref(void)
        {
            return *this;
        }
        ValEnv(void); ///< no implementation. needed for g++ v3.4 compilability
        ValEnv(const T& val)
            : T(val)
            {}
        static T defaulted(void)
        {
            return T();
        }
        static ValEnv* create(from v)
        {
            return new ValEnv(v);
        }
    };

    /// @brief PrEnv - environment that contains a primitive datatype
    template <typename T>
    struct PrEnv : Env
    {
        typedef PrEnv simplify;
        typedef std::string TO;
        typedef const T& from;
        typedef const TO& alt;
        typedef T& preferred;
        preferred pref(void)
        {
            return val;
        }
        T val;
        PrEnv(void); ///< no implementation. needed for g++ v3.4 compilability
        PrEnv(from val)
            : val(val)
            {}
        PrEnv(alt val);
        operator TO (void) const;
        static PrEnv* create(const PrEnv& v)
        {
            return new PrEnv(v);
        }
    };

    /// @brief NoEnv - environment that contains nothing
    /// @invariant type parameter should be <void>
    ///
    template <typename>
    struct NoEnv;

    template <>
    struct NoEnv<void> : Env
    {
        typedef NoEnv simplify;
        typedef const void* from;
        typedef NoEnv& preferred;
        NoEnv(void); ///< no implementation. needed for g++ v3.4 compilability
        NoEnv(from val) {}
        static from defaulted(void)
        {
            return from(0);
        }
        static NoEnv* create(from)
        {
            return 0;
        }
    };
    
    /// @brief RefEnv - environment that closes over a reference
    template <typename T>
    struct RefEnv : Env
    {
        typedef RefEnv simplify;
        typedef T& from;
        typedef T& preferred;
        preferred pref(void)
        {
            return val;
        }
        T& val;
        RefEnv(void); ///< no implementation. needed for g++ v3.4 compilability
        RefEnv(T& val)
            : val(val)
            {}
        static RefEnv* create(from v)
        {
            return new RefEnv(v);
        }
    };

} // namespace

#endif // micker_ENV_hpp
